﻿using System.Collections;
using Google.ProtocolBuffers;
using System.Collections.Generic;
using System;
using System.IO;
using System.Collections.Concurrent;

namespace MyLib
{
    /// <summary>
    /// 发送网络报文的Bundle对象
    /// 客户端发送服务器和服务器发送客户端是同构的协议
    /// </summary>
	public class ServerBundle 
	{
        public bool inUse = false;
        private static ConcurrentQueue<ServerBundle> serverBundlePool = new ConcurrentQueue<ServerBundle>();

        private static ServerBundle GetBundle()
        {
            ServerBundle q = null;
            var has = serverBundlePool.TryDequeue(out q);
            if (has)
            {
                q.inUse = true;
                return q;
            }
            var nb = new ServerBundle();
            nb.inUse = true;
            return nb;
        }

	    public ServerBundle()
	    {
            //协议不能超长 超长需要用MemoryStream 8192, 8192 来做
            coutStream = CodedOutputStream.CreateInstance(new byte[8192]);
	    }

        public static void ReturnBundle(ServerBundle bundle)
        {
            if (bundle == null)
            {
                return;
            }
            if (!bundle.inUse) return;
            bundle.Reset();
            bundle.inUse = false;
            serverBundlePool.Enqueue(bundle);
        }

		//KBEngine.MemoryStream stream = new KBEngine.MemoryStream();
		public KBEngine.Message msgtype = null;
		public byte moduleId;
		public byte msgId;
		public System.Byte flowId = 0;
        public byte ackId = 0;
        public IMessageLite protoMsg;

	    private void Reset()
	    {
	        moduleId = 0;
	        msgId = 0;
	        msgtype = null;
	        flowId = 0;
            //stream.Reset();
            coutStream.ClearBuffer();
        }

		void newMessage(System.Type type) {
			Debug.Log ("ServerBundle:: 开始发送消息 Message is " + type.Name);
			var pa = Util.GetMsgID (type.Name);
            if(pa == null) {
                Debug.LogError("GetMessage Id Error, please Update NameMap.json "+type.Name);
            }
			moduleId = pa.moduleId;
			msgId = pa.messageId;
			
			msgtype = null;
		}

        /// <summary>
        /// 0拷贝 CodedStream-->内部
        /// 协议性能减少写入的复制次数
        /// </summary>
        /// <param name="v"></param>
        /// <param name="errorCode"></param>
        /// <returns></returns>
	    public CodedOutputStream coutStream;
        public int totalBundleLen = 0;

		uint writePB(IMessageLite pbMsg, byte errorCode=0) {
            protoMsg = pbMsg;
			Debug.Log ("WritePB: "+pbMsg);
            coutStream.ClearBuffer();
            coutStream.WriteRawLittleEndian16(0);//占位 
            var headLen = coutStream.position;
            coutStream.WriteRawByte(ackId);
            coutStream.WriteRawByte(flowId);
            coutStream.WriteRawByte(moduleId);
            coutStream.WriteRawByte(msgId);
            //不需要ErrorCode了
            //coutStream.WriteRawByte(errorCode);
            pbMsg.WriteTo(coutStream);

            var totalLen = coutStream.position;
            var bodyLen = totalLen - headLen;

            coutStream.position = 0;
            coutStream.WriteRawLittleEndian16((uint)bodyLen);
            coutStream.position = totalLen;
        
            totalBundleLen = totalLen;
            return (uint)totalLen;
		}

        public static void sendImmediateError(IBuilderLite build,  byte ackId, byte flowId, byte errorCode, out ServerBundle b) {
            var data = build.WeakBuild ();

            //var bundle = new ServerBundle ();
            var bundle = GetBundle();
            b = bundle;
            bundle.newMessage (data.GetType());
            bundle.ackId = ackId;
            bundle.flowId = flowId;
            bundle.writePB (data, errorCode);
            //return bundle.stream.getbuffer();
        }
       
	}
}